package com.cqfae.deploycentral.app.job;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cqfae.deploycentral.app.base.BaseConstants;
import com.cqfae.deploycentral.app.config.TestLinkInfo;
import com.cqfae.deploycentral.app.dao.entity.ReportInfo;
import com.cqfae.deploycentral.app.dao.entity.ReportTestLink;
import com.cqfae.deploycentral.app.dao.mapper.ReportInfoMapper;
import com.cqfae.deploycentral.app.dao.mapper.ReportTestLinkMapper;
import com.cqfae.deploycentral.app.utils.GsonUtils;
import com.cqfae.deploycentral.app.utils.NullUtil;
import com.cqfae.deploycentral.app.utils.QuartzUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Example;

import java.text.MessageFormat;
import java.util.*;

/**
 * Created by JIANGLU009 on 2017/11/29.
 */
public class TestLinkJob implements Job {

    private static Logger logger = LoggerFactory.getLogger(TestLinkJob.class);

    private String sqlReportCode = "reportCode";

    private String mapTestplanid = "testplanid";

    private String mapTprjname = "tprjname";

    private String statMsg;
    private String sitBugMsg;
    private String regBugMsg;

    @Override
    public void execute(JobExecutionContext context) {
        // 设置msg
        statMsg = BaseConstants.getConstantsCodeMap().get("reportMsg.statMsg");
        sitBugMsg = "\n" + BaseConstants.getConstantsCodeMap().get("reportMsg.sitBugMsg") + "\n";
        regBugMsg = "\n" + BaseConstants.getConstantsCodeMap().get("reportMsg.regBugMsg") + "\n";

        // 获得数据
        ApplicationContext applicationContext = QuartzUtil.getApplicaitonContext(context);
        // 上下文获取异常时，跳出
        if (applicationContext == null) {
            return;
        }

        // 设置bean
        RestTemplate restTemplate = applicationContext.getBean(RestTemplate.class);
        ReportInfoMapper reportInfoMapper = applicationContext.getBean(ReportInfoMapper.class);
        TestLinkInfo testLinkInfo = applicationContext.getBean(TestLinkInfo.class);
        ReportTestLinkMapper reportTestLinkMapper = applicationContext.getBean(ReportTestLinkMapper.class);

        // 获取当前任务对应的reportCode
        String jobName = context.getJobDetail().getKey().getName();
        String reportCode = jobName.substring(jobName.indexOf('_') + 1, jobName.length());

        // 获取当前任务对应TESTLINK信息
        ReportTestLink reportTestLink = new ReportTestLink();
        reportTestLink.setReportCode(reportCode);
        List<ReportTestLink> reportTestLinkList = reportTestLinkMapper.select(reportTestLink);

        // testplanList,code=testlink的id，name=testlink项目名称
        List<Map> testplanList = new ArrayList<>();
        for (ReportTestLink reportTestLink1 : reportTestLinkList) {
            Map<String, String> map = new HashMap<>();
            map.put(mapTestplanid, reportTestLink1.getTestplanid());
            map.put(mapTprjname, reportTestLink1.getTprjname());
            testplanList.add(map);
        }

        // 查询TESTLINK数据，并在TESTLINK关闭时关闭job
        if (testplanList != null && !testplanList.isEmpty()) {
            // 取得TESTLLINK数据
            getSITAndREG(reportCode, testplanList, restTemplate, testLinkInfo, reportTestLinkMapper);
            // 更新reportInfo
            updateReportInfo(reportCode, reportInfoMapper, reportTestLinkMapper);
        }
    }

    /**
     * 获得SIT、REG
     *
     * @param reportCode
     * @param testplanList
     * @param restTemplate
     * @param testLinkInfo
     * @param reportTestLinkMapper
     */
    private void getSITAndREG(String reportCode, List<Map> testplanList,
                              RestTemplate restTemplate, TestLinkInfo testLinkInfo, ReportTestLinkMapper reportTestLinkMapper) {
        // 获取数据
        // 取得TESTLLINK数据，一个report可能对应多个TESTLINK
        for (Map<String, String> map : testplanList) {
            if (NullUtil.isNotEmpty(map.get(mapTestplanid))) {
                // 访问url获取数据
                String url = testLinkInfo.getHost() + testLinkInfo.getCounters() + "/" + map.get(mapTestplanid);
                logger.info("getSITAndREG call url:{}", url);
                ResponseEntity<String> responseEntity = restTemplate.exchange(url,
                        HttpMethod.GET, null, String.class);
                String responseEntityStr = GsonUtils.getInstance().toJson(responseEntity);
                logger.info("getSITAndREG return result:{}", responseEntityStr);
                // 调用TESTLINK更新数据
                String bodyStr = responseEntity.getBody();
                JSONObject bodyJson = JSONObject.parseObject(bodyStr);
                // 数据转换
                if (bodyJson != null && !bodyJson.isEmpty()) {
                    setParam(map, bodyJson, "SIT", reportCode, reportTestLinkMapper, testLinkInfo, restTemplate);
                    setParam(map, bodyJson, "REG", reportCode, reportTestLinkMapper, testLinkInfo, restTemplate);
                }
            }
        }
    }

    /**
     * 设置参数
     *
     * @param map
     * @param jsonObject
     * @param type
     * @param reportCode
     * @param reportTestLinkMapper
     */
    private void setParam(Map<String, String> map, JSONObject jsonObject, String type,
                          String reportCode, ReportTestLinkMapper reportTestLinkMapper, TestLinkInfo testLinkInfo, RestTemplate restTemplate) {
        // TESTLINK对应ID
        String code = map.get(mapTestplanid);
        // TESTLINK对应名称
        String name = map.get(mapTprjname);
        // 组装数据
        StringBuilder sb = new StringBuilder();
        // 解析数据
        try {
            if (jsonObject.get("counters") != null) {
                JSONObject countersJson = (JSONObject) jsonObject.get("counters");
                JSONArray jsonArray = (JSONArray) countersJson.get(type);
                if (jsonArray.isEmpty()) {
                    sb.append(getError(map, "", testLinkInfo, restTemplate));
                } else {
                    for (int i = 0; i < jsonArray.size(); i++) {
                        // 组装数据
                        if (i != 0) {
                            sb.append("\n");
                        }
                        JSONObject jsonObject1 = (JSONObject) jsonArray.get(i);
                        JSONObject jsonObjectStat = (JSONObject) jsonObject1.get("stat");

                        String testplaneName = QuartzUtil.getTestplanName(restTemplate, testLinkInfo, name, code);
                        String statMsgStr = MessageFormat.format(statMsg,
                                name,
                                testplaneName,
                                jsonObject1.get("name"),
                                jsonObjectStat.get("total"),
                                jsonObjectStat.get("exec_p"),
                                jsonObjectStat.get("pass_p"),
                                jsonObjectStat.get("fail_p"),
                                jsonObjectStat.get("block_p"));
                        sb.append(statMsgStr);
                    }
                }
            } else {
                sb.append(getError(map, jsonObject.toString(), testLinkInfo, restTemplate));
            }
        } catch (Exception e) {
            sb = new StringBuilder(getError(map, jsonObject.toString(), testLinkInfo, restTemplate));
            logger.info("{} {} {} : {}", name, jsonObject.toString(), e);
        }

        Example example = new Example(ReportTestLink.class);
        example.createCriteria().andEqualTo(sqlReportCode, reportCode).andEqualTo(mapTestplanid, code);
        ReportTestLink reportTestLink = new ReportTestLink();
        if ("SIT".equals(type)) {
            reportTestLink.setSitResult(sb.toString());
        } else {
            reportTestLink.setRegResult(sb.toString());
        }
        reportTestLink.setUpdateBy("TESTLINK");
        reportTestLink.setUpdateTime(new Date());
        reportTestLinkMapper.updateByExampleSelective(reportTestLink, example);
    }

    /**
     * 错误时设置信息，信息获得错误时不能活动测试计划版本数据
     *
     * @param map
     * @param msg
     * @return
     */
    private String getError(Map<String, String> map, String msg, TestLinkInfo testLinkInfo, RestTemplate restTemplate) {
        String testplanId = map.get(mapTestplanid);
        String tprjname = map.get(mapTprjname);
        String error = "{0} {1} ：{2};";
        String testplanName = QuartzUtil.getTestplanName(restTemplate, testLinkInfo, tprjname, testplanId);
        return MessageFormat.format(error, tprjname, testplanName, msg);
    }

    /**
     * 更新reportInfo
     *
     * @param reportCode
     * @param reportInfoMapper
     * @param reportTestLinkMapper
     */
    private void updateReportInfo(String reportCode, ReportInfoMapper reportInfoMapper, ReportTestLinkMapper reportTestLinkMapper) {
        // 更新reportInfo
        ReportInfo entity = new ReportInfo();
        // 设置ReportInfo数据
        QuartzUtil.setReportInfo(reportCode, entity, sitBugMsg, regBugMsg, reportTestLinkMapper);
        // 设置更新人和时间
        entity.setUpdateBy("TESTLINK");
        // 更新唯一条件id
        Example example = new Example(ReportInfo.class);
        example.createCriteria().andEqualTo(sqlReportCode, reportCode);
        reportInfoMapper.updateByExampleSelective(entity, example);
    }

}
